{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "77a5a292",
   "metadata": {},
   "source": [
    "# 基于 Qwen1.5-0.5b 的 RAG 文档问答\n",
    "## 项目介绍\n",
    "本项目旨在利用大语言模型，解析和处理 MindSpore 设计概览 PDF 文档，构建一个智能问答系统。​该系统不仅展示了大语言模型在专业领域文档理解和信息提取方面的能力，同时也为开发者提供了一个实践范例，说明如何结合预训练模型与特定领域知识，打造高效的问答解决方案。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d0f43f46",
   "metadata": {},
   "source": [
    "## Step 1：安装依赖包\n",
    "本项目主要基于 MindSpore NLP 和 Mindspore 进行开发，除上述两个库外，需先安装相关依赖库\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "ac97bb42",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Defaulting to user installation because normal site-packages is not writeable\n",
      "Requirement already satisfied: pymupdf in /home/HwHiAiUser/.local/lib/python3.9/site-packages (1.26.3)\n",
      "Requirement already satisfied: sentence-transformers in /home/HwHiAiUser/.local/lib/python3.9/site-packages (5.0.0)\n",
      "Requirement already satisfied: faiss-cpu in /home/HwHiAiUser/.local/lib/python3.9/site-packages (1.11.0.post1)\n",
      "Requirement already satisfied: mindnlp in /home/HwHiAiUser/.local/lib/python3.9/site-packages (0.4.1)\n",
      "Requirement already satisfied: newspaper3k in /home/HwHiAiUser/.local/lib/python3.9/site-packages (0.2.8)\n",
      "Requirement already satisfied: lxml[html_clean] in /home/HwHiAiUser/.local/lib/python3.9/site-packages (6.0.0)\n",
      "Requirement already satisfied: huggingface-hub>=0.20.0 in /home/HwHiAiUser/.local/lib/python3.9/site-packages (from sentence-transformers) (0.34.4)\n",
      "Requirement already satisfied: Pillow in /usr/local/miniconda3/lib/python3.9/site-packages (from sentence-transformers) (10.2.0)\n",
      "Requirement already satisfied: tqdm in /home/HwHiAiUser/.local/lib/python3.9/site-packages (from sentence-transformers) (4.66.5)\n",
      "Requirement already satisfied: typing_extensions>=4.5.0 in /usr/local/miniconda3/lib/python3.9/site-packages (from sentence-transformers) (4.9.0)\n",
      "Collecting transformers<5.0.0,>=4.41.0\n",
      "  Downloading transformers-4.55.2-py3-none-any.whl (11.3 MB)\n",
      "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m11.3/11.3 MB\u001b[0m \u001b[31m8.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m00:01\u001b[0m00:01\u001b[0m\n",
      "\u001b[?25hRequirement already satisfied: scikit-learn in /usr/local/miniconda3/lib/python3.9/site-packages (from sentence-transformers) (1.4.0)\n",
      "Requirement already satisfied: scipy in /usr/local/miniconda3/lib/python3.9/site-packages (from sentence-transformers) (1.12.0)\n",
      "Requirement already satisfied: torch>=1.11.0 in /usr/local/miniconda3/lib/python3.9/site-packages (from sentence-transformers) (2.1.0)\n",
      "Requirement already satisfied: packaging in /usr/local/miniconda3/lib/python3.9/site-packages (from faiss-cpu) (23.1)\n",
      "Requirement already satisfied: numpy<3.0,>=1.25.0 in /home/HwHiAiUser/.local/lib/python3.9/site-packages (from faiss-cpu) (1.26.4)\n",
      "Requirement already satisfied: pyctcdecode in /home/HwHiAiUser/.local/lib/python3.9/site-packages (from mindnlp) (0.5.0)\n",
      "Requirement already satisfied: tokenizers==0.19.1 in /home/HwHiAiUser/.local/lib/python3.9/site-packages (from mindnlp) (0.19.1)\n",
      "Requirement already satisfied: regex in /home/HwHiAiUser/.local/lib/python3.9/site-packages (from mindnlp) (2024.9.11)\n",
      "Requirement already satisfied: safetensors in /usr/local/miniconda3/lib/python3.9/site-packages (from mindnlp) (0.4.5)\n",
      "Requirement already satisfied: ml-dtypes in /home/HwHiAiUser/.local/lib/python3.9/site-packages (from mindnlp) (0.5.0)\n",
      "Requirement already satisfied: mindspore>=2.2.14 in /home/HwHiAiUser/.local/lib/python3.9/site-packages (from mindnlp) (2.6.0)\n",
      "Requirement already satisfied: pytest==7.2.0 in /home/HwHiAiUser/.local/lib/python3.9/site-packages (from mindnlp) (7.2.0)\n",
      "Requirement already satisfied: sentencepiece in /home/HwHiAiUser/.local/lib/python3.9/site-packages (from mindnlp) (0.2.0)\n",
      "Requirement already satisfied: datasets in /home/HwHiAiUser/.local/lib/python3.9/site-packages (from mindnlp) (3.0.1)\n",
      "Requirement already satisfied: addict in /home/HwHiAiUser/.local/lib/python3.9/site-packages (from mindnlp) (2.4.0)\n",
      "Requirement already satisfied: requests in /home/HwHiAiUser/.local/lib/python3.9/site-packages (from mindnlp) (2.32.3)\n",
      "Requirement already satisfied: evaluate in /home/HwHiAiUser/.local/lib/python3.9/site-packages (from mindnlp) (0.4.3)\n",
      "Requirement already satisfied: exceptiongroup>=1.0.0rc8 in /usr/local/miniconda3/lib/python3.9/site-packages (from pytest==7.2.0->mindnlp) (1.2.0)\n",
      "Requirement already satisfied: tomli>=1.0.0 in /usr/local/miniconda3/lib/python3.9/site-packages (from pytest==7.2.0->mindnlp) (2.0.1)\n",
      "Requirement already satisfied: pluggy<2.0,>=0.12 in /usr/local/miniconda3/lib/python3.9/site-packages (from pytest==7.2.0->mindnlp) (1.0.0)\n",
      "Requirement already satisfied: attrs>=19.2.0 in /usr/local/miniconda3/lib/python3.9/site-packages (from pytest==7.2.0->mindnlp) (23.2.0)\n",
      "Requirement already satisfied: iniconfig in /home/HwHiAiUser/.local/lib/python3.9/site-packages (from pytest==7.2.0->mindnlp) (2.0.0)\n",
      "Requirement already satisfied: PyYAML>=3.11 in /usr/local/miniconda3/lib/python3.9/site-packages (from newspaper3k) (6.0.1)\n",
      "Requirement already satisfied: tldextract>=2.0.1 in /home/HwHiAiUser/.local/lib/python3.9/site-packages (from newspaper3k) (5.3.0)\n",
      "Requirement already satisfied: tinysegmenter==0.3 in /home/HwHiAiUser/.local/lib/python3.9/site-packages (from newspaper3k) (0.3)\n",
      "Requirement already satisfied: beautifulsoup4>=4.4.1 in /usr/local/miniconda3/lib/python3.9/site-packages (from newspaper3k) (4.12.3)\n",
      "Requirement already satisfied: feedparser>=5.2.1 in /home/HwHiAiUser/.local/lib/python3.9/site-packages (from newspaper3k) (6.0.11)\n",
      "Requirement already satisfied: feedfinder2>=0.0.4 in /home/HwHiAiUser/.local/lib/python3.9/site-packages (from newspaper3k) (0.0.4)\n",
      "Requirement already satisfied: python-dateutil>=2.5.3 in /usr/local/miniconda3/lib/python3.9/site-packages (from newspaper3k) (2.8.2)\n",
      "Requirement already satisfied: cssselect>=0.9.2 in /home/HwHiAiUser/.local/lib/python3.9/site-packages (from newspaper3k) (1.3.0)\n",
      "Collecting jieba3k>=0.35.1\n",
      "  Using cached jieba3k-0.35.1-py3-none-any.whl\n",
      "Requirement already satisfied: nltk>=3.2.1 in /home/HwHiAiUser/.local/lib/python3.9/site-packages (from newspaper3k) (3.9.1)\n",
      "\u001b[33mWARNING: lxml 6.0.0 does not provide the extra 'html_clean'\u001b[0m\u001b[33m\n",
      "\u001b[0mRequirement already satisfied: soupsieve>1.2 in /usr/local/miniconda3/lib/python3.9/site-packages (from beautifulsoup4>=4.4.1->newspaper3k) (2.5)\n",
      "Requirement already satisfied: six in /usr/local/miniconda3/lib/python3.9/site-packages (from feedfinder2>=0.0.4->newspaper3k) (1.16.0)\n",
      "Requirement already satisfied: sgmllib3k in /home/HwHiAiUser/.local/lib/python3.9/site-packages (from feedparser>=5.2.1->newspaper3k) (1.0.0)\n",
      "Requirement already satisfied: filelock in /usr/local/miniconda3/lib/python3.9/site-packages (from huggingface-hub>=0.20.0->sentence-transformers) (3.13.1)\n",
      "Requirement already satisfied: hf-xet<2.0.0,>=1.1.3 in /home/HwHiAiUser/.local/lib/python3.9/site-packages (from huggingface-hub>=0.20.0->sentence-transformers) (1.1.7)\n",
      "Requirement already satisfied: fsspec>=2023.5.0 in /usr/local/miniconda3/lib/python3.9/site-packages (from huggingface-hub>=0.20.0->sentence-transformers) (2023.12.2)\n",
      "Requirement already satisfied: astunparse>=1.6.3 in /home/HwHiAiUser/.local/lib/python3.9/site-packages (from mindspore>=2.2.14->mindnlp) (1.6.3)\n",
      "Requirement already satisfied: protobuf>=3.13.0 in /usr/local/miniconda3/lib/python3.9/site-packages (from mindspore>=2.2.14->mindnlp) (3.20.0)\n",
      "Requirement already satisfied: psutil>=5.6.1 in /usr/local/miniconda3/lib/python3.9/site-packages (from mindspore>=2.2.14->mindnlp) (5.9.8)\n",
      "Requirement already satisfied: asttokens>=2.0.4 in /home/HwHiAiUser/.local/lib/python3.9/site-packages (from mindspore>=2.2.14->mindnlp) (2.4.1)\n",
      "Requirement already satisfied: dill>=0.3.7 in /home/HwHiAiUser/.local/lib/python3.9/site-packages (from mindspore>=2.2.14->mindnlp) (0.3.8)\n",
      "Requirement already satisfied: joblib in /usr/local/miniconda3/lib/python3.9/site-packages (from nltk>=3.2.1->newspaper3k) (1.3.2)\n",
      "Requirement already satisfied: click in /usr/local/miniconda3/lib/python3.9/site-packages (from nltk>=3.2.1->newspaper3k) (8.1.7)\n",
      "Requirement already satisfied: urllib3<3,>=1.21.1 in /home/HwHiAiUser/.local/lib/python3.9/site-packages (from requests->mindnlp) (2.2.3)\n",
      "Requirement already satisfied: idna<4,>=2.5 in /usr/local/miniconda3/lib/python3.9/site-packages (from requests->mindnlp) (3.4)\n",
      "Requirement already satisfied: charset-normalizer<4,>=2 in /usr/local/miniconda3/lib/python3.9/site-packages (from requests->mindnlp) (2.0.4)\n",
      "Requirement already satisfied: certifi>=2017.4.17 in /usr/local/miniconda3/lib/python3.9/site-packages (from requests->mindnlp) (2023.11.17)\n",
      "Requirement already satisfied: requests-file>=1.4 in /home/HwHiAiUser/.local/lib/python3.9/site-packages (from tldextract>=2.0.1->newspaper3k) (2.1.0)\n",
      "Requirement already satisfied: networkx in /usr/local/miniconda3/lib/python3.9/site-packages (from torch>=1.11.0->sentence-transformers) (3.2.1)\n",
      "Requirement already satisfied: sympy in /home/HwHiAiUser/.local/lib/python3.9/site-packages (from torch>=1.11.0->sentence-transformers) (1.14.0)\n",
      "Requirement already satisfied: jinja2 in /usr/local/miniconda3/lib/python3.9/site-packages (from torch>=1.11.0->sentence-transformers) (3.1.3)\n",
      "Collecting transformers<5.0.0,>=4.41.0\n",
      "  Downloading transformers-4.55.1-py3-none-any.whl (11.3 MB)\n",
      "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m11.3/11.3 MB\u001b[0m \u001b[31m7.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m00:01\u001b[0m00:01\u001b[0m\n",
      "\u001b[?25h  Downloading transformers-4.55.0-py3-none-any.whl (11.3 MB)\n",
      "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m11.3/11.3 MB\u001b[0m \u001b[31m6.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m00:01\u001b[0m00:01\u001b[0m\n",
      "\u001b[?25h  Downloading transformers-4.54.1-py3-none-any.whl (11.2 MB)\n",
      "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m11.2/11.2 MB\u001b[0m \u001b[31m6.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m00:01\u001b[0m00:01\u001b[0m\n",
      "\u001b[?25h  Downloading transformers-4.54.0-py3-none-any.whl (11.2 MB)\n",
      "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m11.2/11.2 MB\u001b[0m \u001b[31m4.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m00:01\u001b[0m00:01\u001b[0m\n",
      "\u001b[?25h  Downloading transformers-4.53.3-py3-none-any.whl (10.8 MB)\n",
      "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m10.8/10.8 MB\u001b[0m \u001b[31m3.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m00:01\u001b[0m00:01\u001b[0m\n",
      "\u001b[?25h  Using cached transformers-4.53.2-py3-none-any.whl (10.8 MB)\n",
      "  Using cached transformers-4.53.1-py3-none-any.whl (10.8 MB)\n",
      "  Using cached transformers-4.53.0-py3-none-any.whl (10.8 MB)\n",
      "  Using cached transformers-4.52.4-py3-none-any.whl (10.5 MB)\n",
      "  Using cached transformers-4.52.3-py3-none-any.whl (10.5 MB)\n",
      "  Using cached transformers-4.52.2-py3-none-any.whl (10.5 MB)\n",
      "  Using cached transformers-4.52.1-py3-none-any.whl (10.5 MB)\n",
      "  Using cached transformers-4.51.3-py3-none-any.whl (10.4 MB)\n",
      "  Using cached transformers-4.51.2-py3-none-any.whl (10.4 MB)\n",
      "  Using cached transformers-4.51.1-py3-none-any.whl (10.4 MB)\n",
      "  Using cached transformers-4.51.0-py3-none-any.whl (10.4 MB)\n",
      "  Using cached transformers-4.50.3-py3-none-any.whl (10.2 MB)\n",
      "  Using cached transformers-4.50.2-py3-none-any.whl (10.2 MB)\n",
      "  Using cached transformers-4.50.1-py3-none-any.whl (10.2 MB)\n",
      "  Using cached transformers-4.50.0-py3-none-any.whl (10.2 MB)\n",
      "  Using cached transformers-4.49.0-py3-none-any.whl (10.0 MB)\n",
      "  Using cached transformers-4.48.3-py3-none-any.whl (9.7 MB)\n",
      "  Using cached transformers-4.48.2-py3-none-any.whl (9.7 MB)\n",
      "  Using cached transformers-4.48.1-py3-none-any.whl (9.7 MB)\n",
      "  Using cached transformers-4.48.0-py3-none-any.whl (9.7 MB)\n",
      "  Using cached transformers-4.47.1-py3-none-any.whl (10.1 MB)\n",
      "  Using cached transformers-4.47.0-py3-none-any.whl (10.1 MB)\n",
      "  Using cached transformers-4.46.3-py3-none-any.whl (10.0 MB)\n",
      "  Using cached transformers-4.46.2-py3-none-any.whl (10.0 MB)\n",
      "  Using cached transformers-4.46.1-py3-none-any.whl (10.0 MB)\n",
      "  Using cached transformers-4.45.2-py3-none-any.whl (9.9 MB)\n",
      "  Using cached transformers-4.45.1-py3-none-any.whl (9.9 MB)\n",
      "  Using cached transformers-4.45.0-py3-none-any.whl (9.9 MB)\n",
      "  Using cached transformers-4.44.2-py3-none-any.whl (9.5 MB)\n",
      "Requirement already satisfied: pyarrow>=15.0.0 in /home/HwHiAiUser/.local/lib/python3.9/site-packages (from datasets->mindnlp) (17.0.0)\n",
      "Requirement already satisfied: aiohttp in /home/HwHiAiUser/.local/lib/python3.9/site-packages (from datasets->mindnlp) (3.10.10)\n",
      "Requirement already satisfied: xxhash in /home/HwHiAiUser/.local/lib/python3.9/site-packages (from datasets->mindnlp) (3.5.0)\n",
      "Requirement already satisfied: multiprocess in /home/HwHiAiUser/.local/lib/python3.9/site-packages (from datasets->mindnlp) (0.70.16)\n",
      "Requirement already satisfied: pandas in /home/HwHiAiUser/.local/lib/python3.9/site-packages (from datasets->mindnlp) (2.2.3)\n",
      "Requirement already satisfied: hypothesis<7,>=6.14 in /home/HwHiAiUser/.local/lib/python3.9/site-packages (from pyctcdecode->mindnlp) (6.115.2)\n",
      "Requirement already satisfied: pygtrie<3.0,>=2.1 in /home/HwHiAiUser/.local/lib/python3.9/site-packages (from pyctcdecode->mindnlp) (2.5.0)\n",
      "Requirement already satisfied: threadpoolctl>=2.0.0 in /usr/local/miniconda3/lib/python3.9/site-packages (from scikit-learn->sentence-transformers) (3.2.0)\n",
      "Requirement already satisfied: wheel<1.0,>=0.23.0 in /usr/local/miniconda3/lib/python3.9/site-packages (from astunparse>=1.6.3->mindspore>=2.2.14->mindnlp) (0.37.1)\n",
      "Requirement already satisfied: frozenlist>=1.1.1 in /home/HwHiAiUser/.local/lib/python3.9/site-packages (from aiohttp->datasets->mindnlp) (1.4.1)\n",
      "Requirement already satisfied: async-timeout<5.0,>=4.0 in /usr/local/miniconda3/lib/python3.9/site-packages (from aiohttp->datasets->mindnlp) (4.0.3)\n",
      "Requirement already satisfied: yarl<2.0,>=1.12.0 in /home/HwHiAiUser/.local/lib/python3.9/site-packages (from aiohttp->datasets->mindnlp) (1.15.3)\n",
      "Requirement already satisfied: aiohappyeyeballs>=2.3.0 in /home/HwHiAiUser/.local/lib/python3.9/site-packages (from aiohttp->datasets->mindnlp) (2.4.3)\n",
      "Requirement already satisfied: aiosignal>=1.1.2 in /home/HwHiAiUser/.local/lib/python3.9/site-packages (from aiohttp->datasets->mindnlp) (1.3.1)\n",
      "Requirement already satisfied: multidict<7.0,>=4.5 in /home/HwHiAiUser/.local/lib/python3.9/site-packages (from aiohttp->datasets->mindnlp) (6.1.0)\n",
      "Requirement already satisfied: sortedcontainers<3.0.0,>=2.1.0 in /home/HwHiAiUser/.local/lib/python3.9/site-packages (from hypothesis<7,>=6.14->pyctcdecode->mindnlp) (2.4.0)\n",
      "Requirement already satisfied: MarkupSafe>=2.0 in /usr/local/miniconda3/lib/python3.9/site-packages (from jinja2->torch>=1.11.0->sentence-transformers) (2.1.4)\n",
      "Requirement already satisfied: pytz>=2020.1 in /usr/local/miniconda3/lib/python3.9/site-packages (from pandas->datasets->mindnlp) (2023.3.post1)\n",
      "Requirement already satisfied: tzdata>=2022.7 in /home/HwHiAiUser/.local/lib/python3.9/site-packages (from pandas->datasets->mindnlp) (2024.2)\n",
      "Requirement already satisfied: mpmath<1.4,>=1.1.0 in /usr/local/miniconda3/lib/python3.9/site-packages (from sympy->torch>=1.11.0->sentence-transformers) (1.3.0)\n",
      "Requirement already satisfied: propcache>=0.2.0 in /home/HwHiAiUser/.local/lib/python3.9/site-packages (from yarl<2.0,>=1.12.0->aiohttp->datasets->mindnlp) (0.2.0)\n",
      "Installing collected packages: jieba3k, transformers\n",
      "Successfully installed jieba3k-0.35.1 transformers-4.44.2\n"
     ]
    }
   ],
   "source": [
    "!pip install pymupdf sentence-transformers faiss-cpu newspaper3k lxml[html_clean] jieba==0.42.1"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2e0bcfd0-a43e-4903-bf2d-d2af74d8e344",
   "metadata": {},
   "source": [
    "##  Step 2：RAG——加载 PDF 文档"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "da081b03-b2a3-4976-8db1-5ceace6e05cb",
   "metadata": {
    "tags": []
   },
   "source": [
    "#### RAG介绍\n",
    "大语言模型在智能交互、语言理解等方面都展现出了强大能力，然而在实际业务场景中，通用的基础语言大模型往往难以满足特定的业务需求。\n",
    "大模型的知识来源受限于其训练数据，目前主流的大模型，如ChatGPT、文心一言、通义千问等，其训练集主要基于网络公开数据。意味着它们往往难以获取实时、非公开或离线数据中的知识，从而限制了模型在某些专业领域的应用。\n",
    "同时大模型可能面临幻觉问题，由于所有AI模型的底层原理都基于数学概率，大模型的输出实质上是一系列数值运算的结果。在某些情况下，这可能导致模型在不擅长的场景或缺乏相关知识时产生误导性的回答。这种幻觉问题的识别需要使用者具备相应领域的知识，从而限制了使用的效果。\n",
    "再者，数据安全性也是现代社会关注的焦点。在利用大模型处理企业数据时，数据泄露的风险不容忽视。因此，许多企业或者个人用户不愿将私域数据上传至第三方平台进行训练，这在一定程度上限制了通用大模型在实际业务中的应用。\n",
    "\n",
    "为了解决上述问题，检索增强生成（Retrieval Augmented Generation ，RAG）技术应运而生。\n",
    "RAG技术结合了信息检索与自然语言生成，通过从大量文档中检索相关信息来增强大模型的生成能力。在实际操作中，RAG系统会先依据用户的查询需求，在庞大的知识库中迅速定位并检索到高度相关的文档。随后，系统会精心提炼这些文档中的宝贵知识，将其巧妙地融入用户输入文本之中，一同传递给大模型。这一过程不仅为大模型提供了丰富的可参考背景知识，还大幅提升了生成内容的准确性和针对性。\n",
    "\n",
    "RAG的核心架构可以概括为“数据检索+智能生成”。在“数据检索”环节，依赖向量数据库技术，利用其高效的数据存储与检索机制，迅速锁定目标知识；而在“智能生成”阶段，则借助大模型和精细的提示工程技术，将检索到的知识精准利用，最终生成符合需求的答案。\n",
    "\n",
    "项目使用的示例文档可通过下面代码下载并且加载。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "7ab5f0c5",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Downloading data from https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/white_paper/MindSpore_white_paperV1.1.pdf (1.7 MB)\n",
      "\n",
      "file_sizes: 100%|██████████████████████████| 1.83M/1.83M [00:00<00:00, 4.30MB/s]\n",
      "Successfully downloaded file to MindSpore_Design_Overview.pdf\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'MindSpore_Design_Overview.pdf'"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from download import download\n",
    "\n",
    "url = \"https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/white_paper/MindSpore_white_paperV1.1.pdf\"\n",
    "\n",
    "# 下载 MindSpore 设计概览 PDF 文档\n",
    "download(url, \"MindSpore_Design_Overview.pdf\", replace=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "42560d9d-823c-4032-83f0-e2668b119b10",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "import fitz  # PyMuPDF\n",
    "pdf_path = 'MindSpore_Design_Overview.pdf'  # 需提前下载该文档\n",
    "\n",
    "doc = fitz.open(pdf_path)\n",
    "pdf_text = [page.get_text() for page in doc]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0ef95089",
   "metadata": {},
   "source": [
    "## Step 3：清洗 PDF 文本"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "d93daeb5",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "def clean_text(text):\n",
    "    return ' '.join(text.split())\n",
    "pdf_df = pd.DataFrame({\n",
    "    'page': list(range(1, len(pdf_text)+1)),\n",
    "    'text': [clean_text(t) for t in pdf_text]\n",
    "})"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d5bbead1",
   "metadata": {},
   "source": [
    "##  Step 4：切分为语义块"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "d3151230",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "chunks = []\n",
    "for _, row in pdf_df.iterrows():\n",
    "    text = row['text']\n",
    "    for i in range(0, len(text), 300):\n",
    "        chunk = text[i:i+300]\n",
    "        chunks.append(chunk)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a9dd2164",
   "metadata": {},
   "source": [
    "##  Step 5：向量化并构建 FAISS 检索器"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ee0d1b3d-0017-47c6-8517-bceab194698b",
   "metadata": {},
   "source": [
    "由于一般情况下加载的文档字符较多，常常会达到千位万位的数量级，如果大语言模型直接处理整个文档，可能会在分析过长的文本时遇到困难，难以准确抓取所需信息。为有效应对这一挑战，可以需要采取分割策略，将庞大的文档细化为若干小文本块。如此一来，在需要时，我们便可以灵活地调用相关文档片段，从而提升信息处理的准确性和效率。本课题中也将文档切成包含更小数量级的段落，并且每个段落间也有部分字符重叠，确保一个观点的相关背景信息不会因为切分被遗漏。\n",
    "\n",
    "向量化是一个将文本数据转化为向量矩阵的过程，将每个文本块的内容换成向量，并将这些向量存储在向量数据库中，从而实现索引，方便程序在运行时可以快速检索到相关那内容。向量化的模型众多，Openai的ChatGPT-Embedding、百度的ERNIE-Embedding V1以及北京智源人工智能研究院的BGE模型都是目前主流的开源转换模型。\n",
    "\n",
    "数据向量化后，构建索引并将其写入数据库的过程，简称为“数据入库”。在RAG场景下，有多种数据库可供选择，例如FAISS、Chromadb、Elasticsearch以及Milvus等。在选择适合的数据库时，应全面考虑业务的具体需求、硬件配置以及性能要求等诸多因素，以确保选出最适合的数据库方案。本项目采用较通用常见的FAISS数据库进行数据入库操作。\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "33ebd8ce-b2de-43b9-b74f-ed740934d800",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "### 建议下载到本地部署，比较快，可以从魔塔下载或者昇思平台下载\n",
    "!git lfs install\n",
    "!git clone https://www.modelscope.cn/Ceceliachenen/paraphrase-multilingual-MiniLM-L12-v2.git"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "6a266ef1-442e-4610-b040-7ec618ae17d3",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "from sentence_transformers import SentenceTransformer\n",
    "import faiss\n",
    "import numpy as np\n",
    "\n",
    "embed_model = SentenceTransformer('./paraphrase-multilingual-MiniLM-L12-v2')\n",
    "chunk_embeddings = embed_model.encode(chunks)\n",
    "\n",
    "index = faiss.IndexFlatL2(chunk_embeddings.shape[1])\n",
    "index.add(np.array(chunk_embeddings))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cf67a895",
   "metadata": {},
   "source": [
    "##  Step 6：定义检索接口"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "f34b5844",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "def query_pdf(query, top_k=3):\n",
    "    q_vec = embed_model.encode([query])\n",
    "    D, I = index.search(np.array(q_vec), top_k)\n",
    "    return [chunks[i] for i in I[0]]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "15d6f05c",
   "metadata": {},
   "source": [
    "##  Step 7：加载Qwen1.5-0.5b模型\n",
    "本项目使用小规模蒸馏模型\n",
    "\n",
    "基于Mindspore框架和MindSpore NLP库开发安装还是很方便的"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "62545fef-589f-4632-8922-5199ae135300",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "[WARNING] ME(199412:255086666027040,MainProcess):2025-08-16-21:30:04.674.500 [mindspore/context.py:1402] For 'context.set_context', the parameter 'ascend_config' will be deprecated and removed in a future version. Please use the api mindspore.device_context.ascend.op_precision.precision_mode(),\n",
      "                                                       mindspore.device_context.ascend.op_precision.op_precision_mode(),\n",
      "                                                       mindspore.device_context.ascend.op_precision.matmul_allow_hf32(),\n",
      "                                                       mindspore.device_context.ascend.op_precision.conv_allow_hf32(),\n",
      "                                                       mindspore.device_context.ascend.op_tuning.op_compile() instead.\n",
      "Building prefix dict from the default dictionary ...\n",
      "Loading model from cache /tmp/jieba.cache\n",
      "Loading model cost 1.482 seconds.\n",
      "Prefix dict has been built successfully.\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "正在加载模型...\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Qwen2ForCausalLM has generative capabilities, as `prepare_inputs_for_generation` is explicitly overwritten. However, it doesn't directly inherit from `GenerationMixin`.`PreTrainedModel` will NOT inherit from `GenerationMixin`, and this model will lose the ability to call `generate` and other related functions.\n",
      "  - If you are the owner of the model architecture code, please modify your model class such that it inherits from `GenerationMixin` (after `PreTrainedModel`, otherwise you'll get an exception).\n",
      "  - If you are not the owner of the model architecture class, please contact the model code owner to update it.\n",
      "Sliding Window Attention is enabled but not implemented for `eager`; unexpected results may be encountered.\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "模型加载完成！\n"
     ]
    }
   ],
   "source": [
    "import mindspore\n",
    "from mindnlp.transformers import AutoModelForCausalLM, AutoTokenizer\n",
    "from mindnlp.transformers import TextIteratorStreamer\n",
    "from threading import Thread\n",
    "\n",
    "# 加载tokenizer和模型\n",
    "print(\"正在加载模型...\")\n",
    "tokenizer = AutoTokenizer.from_pretrained(\"/home/HwHiAiUser/Qwen1.5-0.5B-Chat\", mirror=\"modelers\", ms_dtype=mindspore.float16)\n",
    "model = AutoModelForCausalLM.from_pretrained(\"/home/HwHiAiUser/Qwen1.5-0.5B-Chat\", mirror=\"modelers\", ms_dtype=mindspore.float16)\n",
    "print(\"模型加载完成！\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "20ecde6c",
   "metadata": {},
   "source": [
    "##  Step 8：构建回答的流式输出函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "bdb00370-ac2b-4e7e-9cc9-3130a535ad2b",
   "metadata": {},
   "outputs": [],
   "source": [
    "system_prompt = \"你是个能根据文档内容回答问题的专家，需要根据用户提供的文档内容来具体解答\"\n",
    "def chat_with_model(user_input):\n",
    "    \"\"\"与模型进行单轮对话，支持流式输出\"\"\"\n",
    "    # 构建消息格式\n",
    "    messages = [\n",
    "        {'role': 'system', 'content': system_prompt},\n",
    "        {'role': 'user', 'content': user_input}\n",
    "    ]\n",
    "    \n",
    "    # 应用聊天模板\n",
    "    input_ids = tokenizer.apply_chat_template(\n",
    "        messages,\n",
    "        add_generation_prompt=True,\n",
    "        return_tensors=\"ms\",\n",
    "        tokenize=True\n",
    "    )\n",
    "    \n",
    "    # 创建流式输出器\n",
    "    streamer = TextIteratorStreamer(tokenizer, timeout=300, skip_prompt=True, skip_special_tokens=True)\n",
    "    \n",
    "    # 生成参数\n",
    "    generate_kwargs = dict(\n",
    "        input_ids=input_ids,\n",
    "        streamer=streamer,\n",
    "        max_new_tokens=1024,\n",
    "        do_sample=True,\n",
    "        top_p=0.9,\n",
    "        temperature=0.1,\n",
    "        num_beams=1,\n",
    "        pad_token_id=tokenizer.eos_token_id\n",
    "    )\n",
    "    \n",
    "    # 在单独线程中启动生成\n",
    "    t = Thread(target=model.generate, kwargs=generate_kwargs)\n",
    "    t.start()\n",
    "    \n",
    "    # 流式输出tokens\n",
    "    full_response = \"\"\n",
    "    for new_token in streamer:\n",
    "        if '</s>' in new_token:  # 检查停止token\n",
    "            break\n",
    "        print(new_token, end=\"\", flush=True)\n",
    "        full_response += new_token\n",
    "    \n",
    "    return full_response"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4e6affcd-f9fd-48c4-a5bf-d4ddbbc23b03",
   "metadata": {},
   "source": [
    "##  Step 9：测试模型结合文档回答的效果"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "a2e6015e-4235-4013-9645-e64fee22f227",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "MindSpore是一种全新的深度学习计算框架，旨在实现易开发、高效执行和全场景覆盖三大目标。MindSpore 由几个主要组件组成：MindExpression（ME）、Mind Compiler（MC）、MindData（MD）、MindRE 和 MindArmour（MA）。其中，MindExpression 是一个用于构建和运行深度学习模型的中间表达，而 MindCompiler 是用于将源代码转换为可执行的机器代码的工具，MindData 是用于存储和管理数据的框架，MindRE 是用于构建和运行深度学习模型的中间表达，MindArmour 是用于构建和运行深度学习模型的中间表达。"
     ]
    }
   ],
   "source": [
    "query=\"什么是MindSpore？具体介绍一下\"\n",
    "retrieved = \"\\n\".join(query_pdf(query))\n",
    "chat_with_model(f\"以下是相关资料：{retrieved}\\n请回答：{query}\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "py39",
   "language": "python",
   "name": "py39"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.23"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
